using System;
using System.Collections.Generic;
using UnityEngine;

namespace EntityKit.Runtime
{
    public class StateMachine
    {
        private readonly Dictionary<Type, IStateNode> mNodes = new Dictionary<Type, IStateNode>(32);
        private readonly Dictionary<Type, List<Type>> mTransitions = new Dictionary<Type, List<Type>>(16);
        private readonly Dictionary<string, object> mBlackboard = new Dictionary<string, object>(16);

        private IStateNode mCurrent;
        private IStateNode mPrevious;
        private bool mHasTransitions = false; // 优化：跟踪是否有转换规则

        /// <summary>
        /// 状态机拥有者
        /// </summary>
        public object OwnerEntity { get; }

        /// <summary>
        /// 当前状态名称
        /// </summary>
        public IStateNode CurrentNode => mCurrent;
        
        /// <summary>
        /// 当前状态的类型名称
        /// </summary>
        public string CurrentStateName => mCurrent?.GetType().Name ?? "None";

        /// <summary>
        /// 上一个状态名称
        /// </summary>
        public IStateNode PreviousNode => mPrevious;
        
        /// <summary>
        /// 上一个状态的类型名称
        /// </summary>
        public string PreviousStateName => mPrevious?.GetType().Name ?? "None";

        /// <summary>
        /// 状态切换事件 (旧状态, 新状态)
        /// </summary>
        public event Action<IStateNode, IStateNode> OnStateChanged;

        public StateMachine(object owner)
        {
            OwnerEntity = owner ?? throw new ArgumentNullException(nameof(owner));
        }

        /// <summary>
        /// 每帧更新状态机
        /// </summary>
        public void Update()
        {
            mCurrent?.OnReason();
            mCurrent?.OnUpdate();
        }

        public void Run<TNode>() where TNode : IStateNode, new()
        {
            Run(typeof(TNode));
        }

        private void Run(Type nodeType)
        {
            if (nodeType == null)
                throw new ArgumentNullException(nameof(nodeType));

            if (!mNodes.TryGetValue(nodeType, out var node))
                throw new Exception($"Entry node not found: {nodeType.Name}");

            mCurrent = node;
            mPrevious = node;
            node.OnEnter();
        }

        /// <summary>
        /// 添加状态节点
        /// </summary>
        public void AddNode<TNode>() where TNode : IStateNode, new()
        {
            var node = new TNode();
            AddNode(node);
        }

        public void AddNode(IStateNode node)
        {
            if (node == null) return;

            var type = node.GetType();
            if (mNodes.ContainsKey(type))
            {
                Debug.LogError($"State node already exists: {type.Name}");
                return;
            }

            node.OnCreate(this);
            mNodes.Add(type, node);
        }

        /// <summary>
        /// 状态转换
        /// </summary>
        public void ChangeState<TNode>() where TNode : IStateNode
        {
            ChangeState(typeof(TNode));
        }

        private void ChangeState(Type nodeType)
        {
            if (nodeType == null) return;

            if (mCurrent == null)
            {
                Run(nodeType);
                return;
            }

            if (!mNodes.TryGetValue(nodeType, out var node))
            {
                Debug.LogError($"State node not found: {nodeType.Name}");
                return;
            }

            var currentType = mCurrent.GetType();
            if (!IsTransitionValid(currentType, nodeType))
            {
                Debug.LogError($"Invalid transition: {currentType.Name} → {nodeType.Name}");
                return;
            }
            
            var prevNode = mCurrent;
            mPrevious = mCurrent;
            mCurrent.OnExit();
            mCurrent = node;
            node.OnEnter();

            // 触发状态切换事件
            OnStateChanged?.Invoke(prevNode, node);
        }

        /// <summary>
        /// 添加状态转换规则
        /// </summary>
        public void AddTransition<TFrom, TTo>() where TFrom : IStateNode where TTo : IStateNode
        {
            AddTransition(typeof(TFrom), typeof(TTo));
        }

        private void AddTransition(Type fromType, Type toType)
        {
            if (fromType == null || toType == null) return;

            if (!mTransitions.TryGetValue(fromType, out var transitions))
            {
                transitions = new List<Type>(4);
                mTransitions[fromType] = transitions;
            }

            if (!transitions.Contains(toType))
            {
                transitions.Add(toType);
            }
            
            // 更新是否有转换规则的标记
            mHasTransitions = mTransitions.Count > 0;
        }
        
        /// <summary>
        /// 移除状态转换规则
        /// </summary>
        public void RemoveTransition<TFrom, TTo>() where TFrom : IStateNode where TTo : IStateNode
        {
            RemoveTransition(typeof(TFrom), typeof(TTo));
        }

        private void RemoveTransition(Type fromType, Type toType)
        {
            if (fromType == null || toType == null) return;

            if (mTransitions.TryGetValue(fromType, out var transitions))
            {
                transitions.Remove(toType);
                // 如果转换列表为空，则移除该条目
                if (transitions.Count == 0)
                {
                    mTransitions.Remove(fromType);
                }
            }
            
            // 更新是否有转换规则的标记
            mHasTransitions = mTransitions.Count > 0;
        }

        /// <summary>
        /// 回退到上一个状态
        /// </summary>
        public void RevertToPrevious()
        {
            if (mPrevious == null) return;

            var prevType = mPrevious.GetType();
            var currType = mCurrent.GetType();

            if (IsTransitionValid(currType, prevType))
            {
                ChangeState(prevType);
            }
            else
            {
                Debug.LogError($"Invalid revert: {currType.Name} → {prevType.Name}");
            }
        }

        /// <summary>
        /// 清空当前状态
        /// </summary>
        public void ClearState()
        {
            mPrevious = mCurrent;
            mCurrent?.OnExit();
            mCurrent = null;
        }

        /// <summary>
        /// 状态检查方法
        /// </summary>
        public bool IsInState<TNode>() where TNode : IStateNode => mCurrent?.GetType() == typeof(TNode);
        
        /// <summary>
        /// 检查当前状态是否为指定类型
        /// </summary>
        public bool IsInState(Type stateType) => mCurrent?.GetType() == stateType;

        public bool WasInState<TNode>() where TNode : IStateNode => mPrevious?.GetType() == typeof(TNode);
        
        /// <summary>
        /// 检查上一个状态是否为指定类型
        /// </summary>
        public bool WasInState(Type stateType) => mPrevious?.GetType() == stateType;

        /// <summary>
        /// 黑板数据操作
        /// </summary>
        public void SetData<T>(string key, T value) => mBlackboard[key] = value;

        public T GetData<T>(string key, T defaultValue = default)
        {
            if (mBlackboard.TryGetValue(key, out var value) && value is T result)
                return result;

            // 不再输出错误日志，因为有时候数据不存在是正常的
            return defaultValue;
        }
        
        /// <summary>
        /// 检查黑板中是否存在指定键
        /// </summary>
        public bool HasData(string key) => mBlackboard.ContainsKey(key);
        
        /// <summary>
        /// 移除黑板中的数据
        /// </summary>
        public bool RemoveData(string key) => mBlackboard.Remove(key);
        
        /// <summary>
        /// 尝试获取黑板中的数据
        /// </summary>
        public bool TryGetData<T>(string key, out T value)
        {
            if (mBlackboard.TryGetValue(key, out var obj) && obj is T result)
            {
                value = result;
                return true;
            }
            
            value = default(T);
            return false;
        }
        
        /// <summary>
        /// 获取黑板中所有数据的键
        /// </summary>
        public ICollection<string> GetAllKeys() => mBlackboard.Keys;

        private bool IsTransitionValid(Type fromType, Type toType)
        {
            // 优化：使用布尔标记而不是每次都检查Count
            if (!mHasTransitions) return true;

            // 检查转换规则
            return mTransitions.TryGetValue(fromType, out var allowedTransitions) &&
                   allowedTransitions.Contains(toType);
        }
        
        /// <summary>
        /// 获取所有状态节点
        /// </summary>
        public IReadOnlyDictionary<Type, IStateNode> GetAllNodes() => mNodes;
        
        /// <summary>
        /// 获取所有转换规则
        /// </summary>
        public IReadOnlyDictionary<Type, List<Type>> GetAllTransitions() => mTransitions;
        
        /// <summary>
        /// 检查是否存在到指定状态的转换规则
        /// </summary>
        public bool CanTransitionTo<TNode>() where TNode : IStateNode
        {
            if (mCurrent == null) return true;
            
            var currentType = mCurrent.GetType();
            var targetType = typeof(TNode);
            
            return IsTransitionValid(currentType, targetType);
        }
    }
}